<template>
  <div>

    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>权限管理</el-breadcrumb-item>
      <el-breadcrumb-item>角色列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片页 -->
    <el-card class="box-card">
      <el-row>
        <el-col :span='4'>
          <el-button type="primary" @click="addRole">添加角色</el-button>
        </el-col>
      </el-row>
    </el-card>
    <!-- /角色信息列表 -->
    <el-table :data="rolesData" stripe border>
      <el-table-column type="expand">
        <template slot-scope="scope">
          <el-row v-for="(item, i) in scope.row.children" :key="item.id" :class="['bdBottom',i==0?'bdTop':'']">
            <el-col :span='5'>
              <el-tag closable @close="deleteRights(scope.row, item.id)">{{item.authName}}</el-tag>
              <i class="el-icon-caret-right"></i>
            </el-col>
            <el-col :span='19'>
              <!-- <el-tag closable>{{item.authName}}</el-tag> -->
              <el-row v-for="(item2,i2) in item.children" :key="item2.id" :class="i2==0?'':'bdTop'">
                <el-col :span='7'>
                  <el-tag type="success" closable @close="deleteRights(scope.row,item2.id)">{{item2.authName}}</el-tag>
                  <i class="el-icon-caret-right"></i>
                </el-col>
                <el-col :span='17'>
                  <el-tag v-for="item3 in item2.children" :key="item3.id" type="warning" closable
                    @close="deleteRights(scope.row,item3.id)">{{item3.authName}}</el-tag>
                </el-col>
              </el-row>
            </el-col>
          </el-row>
        </template>
      </el-table-column>
      <el-table-column label="#" type="index"></el-table-column>
      <el-table-column label="角色名称" prop="roleName"></el-table-column>
      <el-table-column label="角色描述" prop="roleDesc"></el-table-column>
      <el-table-column label="操作" width="400px">
        <template slot-scope="scope">
          <el-button type="primary" icon="el-icon-edit" @click="editRole(scope.row)">编辑</el-button>
          <el-button type="danger" icon="el-icon-delete" @click="deleteRole(scope.row.id)">删除</el-button>
          <el-button type="primary" icon="el-icon-s-tools" @click="handleEditRights(scope.row)">分配权限</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 修改角色权限的对话框 -->
    <el-dialog title="分配权限" :visible.sync="editDialogVisible" width="70%" @close="clearChecked">
      <!-- 权限树@node-click="handleNodeClick" -->
      <el-tree node-key="id" :default-checked-keys="checkedKeys" :data="allRights" :props="defaultProps" show-checkbox
        ref="treeRef" default-expand-all>
      </el-tree>
      <span slot="footer">
        <el-button @click="editDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitRights">确 定</el-button>
      </span>
    </el-dialog>
    <!-- 添加角色对话框 -->
    <el-dialog title="添加角色" :visible.sync="addDialogVisible" @close='clearAddForm'>
      <el-form :model="addFormData" :rules="roleInfoRule" ref="addFormRef">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="addFormData.roleName"></el-input>
        </el-form-item>

        <el-form-item label="角色描述">
          <el-input v-model="addFormData.roleDesc"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="addDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitAdd">添 加</el-button>
      </div>
    </el-dialog>
    <!-- 编辑角色的对话框 -->
    <el-dialog title="修改角色" :visible.sync="roleDialogVisible" @close='roleFormData = {}'>
      <el-form :model="roleFormData" :rules="roleInfoRule" ref="editRoleRef">
        <el-form-item label="角色ID">
          <el-input v-model="roleFormData.roleId" disabled></el-input>
        </el-form-item>

        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="roleFormData.roleName"></el-input>
        </el-form-item>

        <el-form-item label="角色描述">
          <el-input v-model="roleFormData.roleDesc"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="roleDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitRole">确 定</el-button>
      </div>
    </el-dialog>
  </div>

</template>
<style lang="less" scoped>
  .el-breadcrumb {
    margin-bottom: 30px;
  }

  .bdTop {
    border-top: 1px solid rgb(233, 233, 233);
  }

  .bdBottom {
    border-bottom: 1px solid rgb(233, 233, 233);
  }

  .el-tag {
    margin: 10px;
  }

  .el-row {
    display: flex;
    align-items: center;
  }

</style>
<script>
  export default {
    data() {
      return {
        rolesData: [],
        editDialogVisible: false,
        treeData: [],
        defaultProps: {
          children: 'children',
          label: 'authName'
        },
        allRights: [],
        checkedKeys: [],
        roleId: null,
        roleFormData: {},
        roleDialogVisible: false,
        addDialogVisible: false,
        addFormData: {},
        roleInfoRule: {
          roleName: [{
            required: true,
            message: '请输入角色名称',
            trigger: 'blur'
          }]
        }
      }
    },
    created() {
      this.getRolesData();
    },
    methods: {
      //获取角色数据，包括各个角色拥有的权限
      async getRolesData() {
        const {
          data: response
        } = await this.$http.get('/roles');
        if (response.meta.status == 200) {
          this.rolesData = response.data;
        } else {
          this.$message.error(response.meta.msg);
        }
      },
      //删除某一个角色的某一个权限
      async deleteRights(role, rightId) {
        this.$confirm('此操作将删除用户的权限, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(async () => {
          const {
            data: response
          } = await this.$http.delete(`roles/${role.id}/rights/${rightId}`);
          if (response.meta.status == 200) {
            role.children = response.data;
          } else {
            this.$message.error(response.meta.msg);
          }
          this.$message({
            type: 'success',
            message: '删除成功!'
          });
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      },
      //显示权限树
      handleEditRights(role) {
        this.getLeafKeys(role, this.checkedKeys);
        this.getAllRights();
        this.roleId = role.id;
        // 出现问题？先出现空的选框，然后再选上，原因是editDialogVisible变化太快了，tree还没有准备好。
      },
      //确认修改权限
      async submitRights(roleId) {
        this.editDialogVisible = false;
        //获取现在的叶子节点
        const LeafNodes = this.$refs.treeRef.getCheckedNodes(true);
        var checkedKeysFixed = [];
        // 得到叶子节点的ID
        LeafNodes.forEach(element => {
          checkedKeysFixed.push(element.id);
        });
        //与原先的叶子节点ID对比
        if (checkedKeysFixed.sort().toString() != this.checkedKeys.sort().toString()) {
          const checked = this.$refs.treeRef.getCheckedNodes(false, true);
          var ids = this.$refs.treeRef.getCheckedKeys();
          var idsString = ids.join(',');
          var {
            data: response
          } = await this.$http.post(`/roles/${this.roleId + 0}/rights`, {
            rids: idsString
          });
          if (response.meta.status == 200) {
            this.$message.success(response.meta.msg);
            this.getRolesData();
          } else {
            this.$message.error(response.meta.msg);
          }
        }
      },
      //获取所有的权限，便于渲染出权限树。
      async getAllRights() {
        const {
          data: response
        } = await this.$http.get('/rights/tree')
        if (response.meta.status == 200) {
          this.allRights = response.data;
          this.getRolesData();
          this.editDialogVisible = true;
        } else {
          this.$message.error(response.meta.msg);
        }

      },
      getLeafKeys(node, arr) {
        if (!node.children) {
          return arr.push(node.id)
        } else {
          node.children.forEach(element => {
            this.getLeafKeys(element, arr)
          });
        }
      },
      clearChecked() {
        this.checkedKeys = [];
      },
      // 编辑角色信息
      editRole(role) {
        // 先要显示原来角色的信息
        this.roleFormData = {
          roleId: role.id,
          roleName: role.roleName,
          roleDesc: role.roleDesc
        };
        this.roleDialogVisible = true;

      },
      // 然后发送修改之后的值
      async submitRole() {
        this.$refs.editRoleRef.validate(async (result) => {
          if (result) {
            const {
              data: response
            } = await this.$http.put(`/roles/${this.roleFormData.roleId + 0}`, {
              roleName: this.roleFormData.roleName,
              roleDesc: this.roleFormData.roleDesc
            });
            if (response.meta.status == 200) {
              this.$message.success(response.meta.msg);
              this.getRolesData();
            } else {
              this.$message.error(response.meta.msg);
            }
            this.roleDialogVisible = false;
          }
        })
      },
      // 删除角色
      async deleteRole(id) {

        this.$confirm('此操作将删除该角色, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(async () => {
          const {
            data: response
          } = await this.$http.delete(`/roles/${id}`);
          if (response.meta.status == 200) {
            this.$message.success(response.meta.msg);
            this.getRolesData();
          } else {
            this.$message.error(response.meta.msg);
          }
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      },
      //添加角色
      addRole() {
        this.addDialogVisible = true;
      },
      //提交信息
      submitAdd() {
        //验证表单项是否符合规则。
        this.$refs.addFormRef.validate(async (result) => {
          if (result) {
            this.addDialogVisible = false;
            const {
              data: response
            } = await this.$http.post('/roles', this.addFormData);
            if (response.meta.status == 201) {
              this.$message.success(response.meta.msg);
            } else {
              this.$message.error(response.meta.msg);
            }
            this.getRolesData();
          }
        })
      },
      clearAddForm() {
        this.$refs.addFormRef.resetFields();
        this.addFormData = {};
      }
    }
  }

</script>
